//
// Created by xinhua on 2021/10/24.
//

#include "SphereBufferGeometry.h"

SphereBufferGeometry::SphereBufferGeometry(float radius, const int heightSegments, const int widthSegments) {
    type = GET_CLASS(__FILE__);
    name = type + "_" + id;

    this->radius = radius;
    this->heightSegments = heightSegments;
    this->widthSegments = widthSegments;
}

SphereBufferGeometry::~SphereBufferGeometry() {

}

void SphereBufferGeometry::onInit() {

    // 角度
    float phiStart = 0;
    float phiLength = M_PI * 2;

    float thetaStart = 0;
    float thetaLength = M_PI;
    float thetaEnd = fmin(thetaStart + thetaLength, M_PI);

    std::vector<std::vector<int>> grid;
    int index = 0;

    //for y
    for(int iy = 0; iy <= heightSegments; iy++){
        std::vector<int> verticesRow;

        float v = iy / (heightSegments * 1.0f);

        float uOffset = 0;

        if(iy == 0 && thetaStart == 0){
            uOffset = 0.5 / widthSegments;
        }else if(iy == heightSegments && thetaEnd == M_PI){
            uOffset = - 0.5 / widthSegments;
        }

        //for x
        for(int ix = 0; ix <= widthSegments; ix ++){
            float u = ix / (widthSegments * 1.0f);

            float x = - radius * cos(phiStart + u * phiLength) * sin(phiStart + v * phiLength);
            float y = radius * cos(phiStart + v * phiLength);
            float z = radius * sin(phiStart + u * phiLength) * sin(phiStart + v * phiLength);

            vertices.push_back(x);
            vertices.push_back(y);
            vertices.push_back(z);

            verticesRow.push_back(index++);
        }

        grid.push_back(verticesRow);
    }

    // indices
    for ( int iy = 0; iy < heightSegments; iy ++ ) {

        for ( int ix = 0; ix < widthSegments; ix ++ ) {

            int a = grid[ iy ][ ix + 1 ];
            int b = grid[ iy ][ ix ];
            int c = grid[ iy + 1 ][ ix ];
            int d = grid[ iy + 1 ][ ix + 1 ];

            if ( iy != 0 || thetaStart > 0 ) {
                indices.push_back(a );
                indices.push_back(b );
                indices.push_back(d );
            }

            if ( iy != heightSegments - 1 || thetaEnd < M_PI ) {
                indices.push_back(b);
                indices.push_back(c);
                indices.push_back(d);
            }

        }
    }
}


void SphereBufferGeometry::drawUI() {
    BufferGeometry::drawUI();
    bool refreshAttri = false;

    if(ImGui::SliderInt("HeightSegments", &heightSegments, 3, 50)){
        refreshAttri = true;
    }
    if(ImGui::SliderInt("WidthSegments", &widthSegments, 3, 50)) {
        refreshAttri = true;
    }

    if(refreshAttri){
        onInit();
    }
}















